/*
 * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
/*
 * Copyright 2001-2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.sun.org.apache.xerces.internal.impl.xs;

import java.lang.ref.SoftReference;
import java.util.Vector;

import com.sun.org.apache.xerces.internal.impl.Constants;
import com.sun.org.apache.xerces.internal.impl.dv.SchemaDVFactory;
import com.sun.org.apache.xerces.internal.impl.dv.ValidatedInfo;
import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType;
import com.sun.org.apache.xerces.internal.impl.dv.xs.XSSimpleTypeDecl;
import com.sun.org.apache.xerces.internal.impl.xs.identity.IdentityConstraint;
import com.sun.org.apache.xerces.internal.impl.xs.util.ObjectListImpl;
import com.sun.org.apache.xerces.internal.impl.xs.util.SimpleLocator;
import com.sun.org.apache.xerces.internal.impl.xs.util.StringListImpl;
import com.sun.org.apache.xerces.internal.impl.xs.util.XSNamedMap4Types;
import com.sun.org.apache.xerces.internal.impl.xs.util.XSNamedMapImpl;
import com.sun.org.apache.xerces.internal.impl.xs.util.XSObjectListImpl;
import com.sun.org.apache.xerces.internal.parsers.DOMParser;
import com.sun.org.apache.xerces.internal.parsers.SAXParser;
import com.sun.org.apache.xerces.internal.parsers.XML11Configuration;
import com.sun.org.apache.xerces.internal.util.SymbolHash;
import com.sun.org.apache.xerces.internal.util.SymbolTable;
import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription;
import com.sun.org.apache.xerces.internal.xni.grammars.XSGrammar;
import com.sun.org.apache.xerces.internal.xs.StringList;
import com.sun.org.apache.xerces.internal.xs.XSAnnotation;
import com.sun.org.apache.xerces.internal.xs.XSAttributeDeclaration;
import com.sun.org.apache.xerces.internal.xs.XSAttributeGroupDefinition;
import com.sun.org.apache.xerces.internal.xs.XSConstants;
import com.sun.org.apache.xerces.internal.xs.XSElementDeclaration;
import com.sun.org.apache.xerces.internal.xs.XSModel;
import com.sun.org.apache.xerces.internal.xs.XSModelGroupDefinition;
import com.sun.org.apache.xerces.internal.xs.XSNamedMap;
import com.sun.org.apache.xerces.internal.xs.XSNamespaceItem;
import com.sun.org.apache.xerces.internal.xs.XSNotationDeclaration;
import com.sun.org.apache.xerces.internal.xs.XSObjectList;
import com.sun.org.apache.xerces.internal.xs.XSParticle;
import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
import com.sun.org.apache.xerces.internal.xs.XSWildcard;
import com.sun.org.apache.xerces.internal.xs.datatypes.ObjectList;
import org.xml.sax.SAXException;

/**
 * This class is to hold all schema component declaration that are declared
 * within one namespace.
 *
 * The Grammar class this class extends contains what little
 * commonality there is between XML Schema and DTD grammars.  It's
 * useful to distinguish grammar objects from other kinds of object
 * when they exist in pools or caches.
 *
 * @author Sandy Gao, IBM
 * @author Elena Litani, IBM
 * @version $Id: SchemaGrammar.java,v 1.7 2010-11-01 04:39:55 joehw Exp $
 * @xerces.internal
 */

public class SchemaGrammar implements XSGrammar, XSNamespaceItem {

  // the target namespace of grammar
  String fTargetNamespace;

  // global decls: map from decl name to decl object
  SymbolHash fGlobalAttrDecls;
  SymbolHash fGlobalAttrGrpDecls;
  SymbolHash fGlobalElemDecls;
  SymbolHash fGlobalGroupDecls;
  SymbolHash fGlobalNotationDecls;
  SymbolHash fGlobalIDConstraintDecls;
  SymbolHash fGlobalTypeDecls;

  // extended global decls: map from schema location + decl name to decl object
  // key is location,name
  SymbolHash fGlobalAttrDeclsExt;
  SymbolHash fGlobalAttrGrpDeclsExt;
  SymbolHash fGlobalElemDeclsExt;
  SymbolHash fGlobalGroupDeclsExt;
  SymbolHash fGlobalNotationDeclsExt;
  SymbolHash fGlobalIDConstraintDeclsExt;
  SymbolHash fGlobalTypeDeclsExt;

  // A global map of all global element declarations - used for substitution group computation
  // (handy when sharing components by reference, since we might end up with duplicate components
  //  that are not added to either of the global element declarations above)
  SymbolHash fAllGlobalElemDecls;

  // the XMLGrammarDescription member
  XSDDescription fGrammarDescription = null;

  // annotations associated with the "root" schema of this targetNamespace
  XSAnnotationImpl[] fAnnotations = null;

  // number of annotations declared
  int fNumAnnotations;

  // symbol table for constructing parsers (annotation support)
  private SymbolTable fSymbolTable = null;
  // parsers for annotation support
  private SoftReference fSAXParser = null;
  private SoftReference fDOMParser = null;

  // is this grammar immutable?  (fully constructed and not changeable)
  private boolean fIsImmutable = false;

  //
  // Constructors
  //

  // needed to make BuiltinSchemaGrammar work.
  protected SchemaGrammar() {
  }

  /**
   * Default constructor.
   *
   * @param grammarDesc the XMLGrammarDescription corresponding to this objec at the least a
   * systemId should always be known.
   * @param symbolTable needed for annotation support
   */
  public SchemaGrammar(String targetNamespace, XSDDescription grammarDesc,
      SymbolTable symbolTable) {
    fTargetNamespace = targetNamespace;
    fGrammarDescription = grammarDesc;
    fSymbolTable = symbolTable;

    // REVISIT: do we know the numbers of the following global decls
    // when creating this grammar? If so, we can pass the numbers in,
    // and use that number to initialize the following hashtables.
    fGlobalAttrDecls = new SymbolHash();
    fGlobalAttrGrpDecls = new SymbolHash();
    fGlobalElemDecls = new SymbolHash();
    fGlobalGroupDecls = new SymbolHash();
    fGlobalNotationDecls = new SymbolHash();
    fGlobalIDConstraintDecls = new SymbolHash();

    // Extended tables
    fGlobalAttrDeclsExt = new SymbolHash();
    fGlobalAttrGrpDeclsExt = new SymbolHash();
    fGlobalElemDeclsExt = new SymbolHash();
    fGlobalGroupDeclsExt = new SymbolHash();
    fGlobalNotationDeclsExt = new SymbolHash();
    fGlobalIDConstraintDeclsExt = new SymbolHash();
    fGlobalTypeDeclsExt = new SymbolHash();

    // All global elements table
    fAllGlobalElemDecls = new SymbolHash();

    // if we are parsing S4S, put built-in types in first
    // they might get overwritten by the types from S4S, but that's
    // considered what the application wants to do.
    if (fTargetNamespace == SchemaSymbols.URI_SCHEMAFORSCHEMA) {
      fGlobalTypeDecls = SG_SchemaNS.fGlobalTypeDecls.makeClone();
    } else {
      fGlobalTypeDecls = new SymbolHash();
    }
  } // <init>(String, XSDDescription)

  // Clone an existing schema grammar
  public SchemaGrammar(SchemaGrammar grammar) {
    fTargetNamespace = grammar.fTargetNamespace;
    fGrammarDescription = grammar.fGrammarDescription.makeClone();
    //fGrammarDescription.fContextType |= XSDDescription.CONTEXT_COLLISION; // REVISIT
    fSymbolTable = grammar.fSymbolTable; // REVISIT

    fGlobalAttrDecls = grammar.fGlobalAttrDecls.makeClone();
    fGlobalAttrGrpDecls = grammar.fGlobalAttrGrpDecls.makeClone();
    fGlobalElemDecls = grammar.fGlobalElemDecls.makeClone();
    fGlobalGroupDecls = grammar.fGlobalGroupDecls.makeClone();
    fGlobalNotationDecls = grammar.fGlobalNotationDecls.makeClone();
    fGlobalIDConstraintDecls = grammar.fGlobalIDConstraintDecls.makeClone();
    fGlobalTypeDecls = grammar.fGlobalTypeDecls.makeClone();

    // Extended tables
    fGlobalAttrDeclsExt = grammar.fGlobalAttrDeclsExt.makeClone();
    fGlobalAttrGrpDeclsExt = grammar.fGlobalAttrGrpDeclsExt.makeClone();
    fGlobalElemDeclsExt = grammar.fGlobalElemDeclsExt.makeClone();
    fGlobalGroupDeclsExt = grammar.fGlobalGroupDeclsExt.makeClone();
    fGlobalNotationDeclsExt = grammar.fGlobalNotationDeclsExt.makeClone();
    fGlobalIDConstraintDeclsExt = grammar.fGlobalIDConstraintDeclsExt.makeClone();
    fGlobalTypeDeclsExt = grammar.fGlobalTypeDeclsExt.makeClone();

    // All global elements table
    fAllGlobalElemDecls = grammar.fAllGlobalElemDecls.makeClone();

    // Annotations associated with the "root" schema of this targetNamespace
    fNumAnnotations = grammar.fNumAnnotations;
    if (fNumAnnotations > 0) {
      fAnnotations = new XSAnnotationImpl[grammar.fAnnotations.length];
      System.arraycopy(grammar.fAnnotations, 0, fAnnotations, 0, fNumAnnotations);
    }

    // All substitution group information declared in this namespace
    fSubGroupCount = grammar.fSubGroupCount;
    if (fSubGroupCount > 0) {
      fSubGroups = new XSElementDecl[grammar.fSubGroups.length];
      System.arraycopy(grammar.fSubGroups, 0, fSubGroups, 0, fSubGroupCount);
    }

    // Array to store complex type decls for constraint checking
    fCTCount = grammar.fCTCount;
    if (fCTCount > 0) {
      fComplexTypeDecls = new XSComplexTypeDecl[grammar.fComplexTypeDecls.length];
      fCTLocators = new SimpleLocator[grammar.fCTLocators.length];
      System.arraycopy(grammar.fComplexTypeDecls, 0, fComplexTypeDecls, 0, fCTCount);
      System.arraycopy(grammar.fCTLocators, 0, fCTLocators, 0, fCTCount);
    }

    // Groups being redefined by restriction
    fRGCount = grammar.fRGCount;
    if (fRGCount > 0) {
      fRedefinedGroupDecls = new XSGroupDecl[grammar.fRedefinedGroupDecls.length];
      fRGLocators = new SimpleLocator[grammar.fRGLocators.length];
      System.arraycopy(grammar.fRedefinedGroupDecls, 0, fRedefinedGroupDecls, 0, fRGCount);
      System.arraycopy(grammar.fRGLocators, 0, fRGLocators, 0, fRGCount);
    }

    // List of imported grammars
    if (grammar.fImported != null) {
      fImported = new Vector();
      for (int i = 0; i < grammar.fImported.size(); i++) {
        fImported.add(grammar.fImported.elementAt(i));
      }
    }

    // Locations
    if (grammar.fLocations != null) {
      for (int k = 0; k < grammar.fLocations.size(); k++) {
        addDocument(null, (String) grammar.fLocations.elementAt(k));
      }
    }

  } // <init>(String, XSDDescription)

  // number of built-in XSTypes we need to create for base and full
  // datatype set
  private static final int BASICSET_COUNT = 29;
  private static final int FULLSET_COUNT = 46;

  private static final int GRAMMAR_XS = 1;
  private static final int GRAMMAR_XSI = 2;

  // this class makes sure the static, built-in schema grammars
  // are immutable.
  public static class BuiltinSchemaGrammar extends SchemaGrammar {

    private static final String EXTENDED_SCHEMA_FACTORY_CLASS = "com.sun.org.apache.xerces.internal.impl.dv.xs.ExtendedSchemaDVFactoryImpl";

    /**
     * Special constructor to create the grammars for the schema namespaces
     */
    public BuiltinSchemaGrammar(int grammar, short schemaVersion) {
      SchemaDVFactory schemaFactory;
      if (schemaVersion == Constants.SCHEMA_VERSION_1_0) {
        schemaFactory = SchemaDVFactory.getInstance();
      } else {
        schemaFactory = SchemaDVFactory.getInstance(EXTENDED_SCHEMA_FACTORY_CLASS);
      }

      if (grammar == GRAMMAR_XS) {
        // target namespace
        fTargetNamespace = SchemaSymbols.URI_SCHEMAFORSCHEMA;

        // grammar description
        fGrammarDescription = new XSDDescription();
        fGrammarDescription.fContextType = XSDDescription.CONTEXT_PREPARSE;
        fGrammarDescription.setNamespace(SchemaSymbols.URI_SCHEMAFORSCHEMA);

        // no global decls other than types
        fGlobalAttrDecls = new SymbolHash(1);
        fGlobalAttrGrpDecls = new SymbolHash(1);
        fGlobalElemDecls = new SymbolHash(1);
        fGlobalGroupDecls = new SymbolHash(1);
        fGlobalNotationDecls = new SymbolHash(1);
        fGlobalIDConstraintDecls = new SymbolHash(1);

        // no extended global decls
        fGlobalAttrDeclsExt = new SymbolHash(1);
        fGlobalAttrGrpDeclsExt = new SymbolHash(1);
        fGlobalElemDeclsExt = new SymbolHash(1);
        fGlobalGroupDeclsExt = new SymbolHash(1);
        fGlobalNotationDeclsExt = new SymbolHash(1);
        fGlobalIDConstraintDeclsExt = new SymbolHash(1);
        fGlobalTypeDeclsExt = new SymbolHash(1);

        // all global element decls table
        fAllGlobalElemDecls = new SymbolHash(1);

        // get all built-in types
        fGlobalTypeDecls = schemaFactory.getBuiltInTypes();

        // assign the built-in schema grammar as the XSNamespaceItem
        // for each of the built-in simple type definitions.
        int length = fGlobalTypeDecls.getLength();
        XSTypeDefinition[] typeDefinitions = new XSTypeDefinition[length];
        fGlobalTypeDecls.getValues(typeDefinitions, 0);
        for (int i = 0; i < length; ++i) {
          XSTypeDefinition xtd = typeDefinitions[i];
          if (xtd instanceof XSSimpleTypeDecl) {
            ((XSSimpleTypeDecl) xtd).setNamespaceItem(this);
          }
        }

        // add anyType
        fGlobalTypeDecls.put(fAnyType.getName(), fAnyType);
      } else if (grammar == GRAMMAR_XSI) {
        // target namespace
        fTargetNamespace = SchemaSymbols.URI_XSI;
        // grammar description
        fGrammarDescription = new XSDDescription();
        fGrammarDescription.fContextType = XSDDescription.CONTEXT_PREPARSE;
        fGrammarDescription.setNamespace(SchemaSymbols.URI_XSI);

        // no global decls other than attributes
        fGlobalAttrGrpDecls = new SymbolHash(1);
        fGlobalElemDecls = new SymbolHash(1);
        fGlobalGroupDecls = new SymbolHash(1);
        fGlobalNotationDecls = new SymbolHash(1);
        fGlobalIDConstraintDecls = new SymbolHash(1);
        fGlobalTypeDecls = new SymbolHash(1);

        // no extended global decls
        fGlobalAttrDeclsExt = new SymbolHash(1);
        fGlobalAttrGrpDeclsExt = new SymbolHash(1);
        fGlobalElemDeclsExt = new SymbolHash(1);
        fGlobalGroupDeclsExt = new SymbolHash(1);
        fGlobalNotationDeclsExt = new SymbolHash(1);
        fGlobalIDConstraintDeclsExt = new SymbolHash(1);
        fGlobalTypeDeclsExt = new SymbolHash(1);

        // no all global element decls
        fAllGlobalElemDecls = new SymbolHash(1);

        // 4 attributes, so initialize the size as 4*2 = 8
        fGlobalAttrDecls = new SymbolHash(8);
        String name = null;
        String tns = null;
        XSSimpleType type = null;
        short scope = XSConstants.SCOPE_GLOBAL;

        // xsi:type
        name = SchemaSymbols.XSI_TYPE;
        tns = SchemaSymbols.URI_XSI;
        type = schemaFactory.getBuiltInType(SchemaSymbols.ATTVAL_QNAME);
        fGlobalAttrDecls.put(name, new BuiltinAttrDecl(name, tns, type, scope));

        // xsi:nil
        name = SchemaSymbols.XSI_NIL;
        tns = SchemaSymbols.URI_XSI;
        type = schemaFactory.getBuiltInType(SchemaSymbols.ATTVAL_BOOLEAN);
        fGlobalAttrDecls.put(name, new BuiltinAttrDecl(name, tns, type, scope));

        XSSimpleType anyURI = schemaFactory.getBuiltInType(SchemaSymbols.ATTVAL_ANYURI);

        // xsi:schemaLocation
        name = SchemaSymbols.XSI_SCHEMALOCATION;
        tns = SchemaSymbols.URI_XSI;
        type = schemaFactory
            .createTypeList("#AnonType_schemaLocation", SchemaSymbols.URI_XSI, (short) 0, anyURI,
                null);
        if (type instanceof XSSimpleTypeDecl) {
          ((XSSimpleTypeDecl) type).setAnonymous(true);
        }
        fGlobalAttrDecls.put(name, new BuiltinAttrDecl(name, tns, type, scope));

        // xsi:noNamespaceSchemaLocation
        name = SchemaSymbols.XSI_NONAMESPACESCHEMALOCATION;
        tns = SchemaSymbols.URI_XSI;
        type = anyURI;
        fGlobalAttrDecls.put(name, new BuiltinAttrDecl(name, tns, type, scope));
      }
    } // <init>(int)

    // return the XMLGrammarDescription corresponding to this
    // object
    public XMLGrammarDescription getGrammarDescription() {
      return fGrammarDescription.makeClone();
    } // getGrammarDescription():  XMLGrammarDescription

    // override these methods solely so that these
    // objects cannot be modified once they're created.
    public void setImportedGrammars(Vector importedGrammars) {
      // ignore
    }

    public void addGlobalAttributeDecl(XSAttributeDecl decl) {
      // ignore
    }

    public void addGlobalAttributeDecl(XSAttributeDecl decl, String location) {
      // ignore
    }

    public void addGlobalAttributeGroupDecl(XSAttributeGroupDecl decl) {
      // ignore
    }

    public void addGlobalAttributeGroupDecl(XSAttributeGroupDecl decl, String location) {
      // ignore
    }

    public void addGlobalElementDecl(XSElementDecl decl) {
      // ignore
    }

    public void addGlobalElementDecl(XSElementDecl decl, String location) {
      // ignore
    }

    public void addGlobalElementDeclAll(XSElementDecl decl) {
      // ignore
    }

    public void addGlobalGroupDecl(XSGroupDecl decl) {
      // ignore
    }

    public void addGlobalGroupDecl(XSGroupDecl decl, String location) {
      // ignore
    }

    public void addGlobalNotationDecl(XSNotationDecl decl) {
      // ignore
    }

    public void addGlobalNotationDecl(XSNotationDecl decl, String location) {
      // ignore
    }

    public void addGlobalTypeDecl(XSTypeDefinition decl) {
      // ignore
    }

    public void addGlobalTypeDecl(XSTypeDefinition decl, String location) {
      // ignore
    }

    public void addGlobalComplexTypeDecl(XSComplexTypeDecl decl) {
      // ignore
    }

    public void addGlobalComplexTypeDecl(XSComplexTypeDecl decl, String location) {
      // ignore
    }

    public void addGlobalSimpleTypeDecl(XSSimpleType decl) {
      // ignore
    }

    public void addGlobalSimpleTypeDecl(XSSimpleType decl, String location) {
      // ignore
    }

    public void addComplexTypeDecl(XSComplexTypeDecl decl, SimpleLocator locator) {
      // ignore
    }

    public void addRedefinedGroupDecl(XSGroupDecl derived, XSGroupDecl base,
        SimpleLocator locator) {
      // ignore
    }

    public synchronized void addDocument(Object document, String location) {
      // ignore
    }

    // annotation support
    synchronized DOMParser getDOMParser() {
      return null;
    }

    synchronized SAXParser getSAXParser() {
      return null;
    }
  }

  /**
   * <p>A partial schema for schemas for validating annotations.</p>
   *
   * @author Michael Glavassevich, IBM
   * @xerces.internal
   */
  public static final class Schema4Annotations extends SchemaGrammar {

    /**
     * Singleton instance.
     */
    public static final Schema4Annotations INSTANCE = new Schema4Annotations();

    /**
     * Special constructor to create a schema
     * capable of validating annotations.
     */
    private Schema4Annotations() {

      // target namespace
      fTargetNamespace = SchemaSymbols.URI_SCHEMAFORSCHEMA;

      // grammar description
      fGrammarDescription = new XSDDescription();
      fGrammarDescription.fContextType = XSDDescription.CONTEXT_PREPARSE;
      fGrammarDescription.setNamespace(SchemaSymbols.URI_SCHEMAFORSCHEMA);

      // no global decls other than types and
      // element declarations for <annotation>, <documentation> and <appinfo>.
      fGlobalAttrDecls = new SymbolHash(1);
      fGlobalAttrGrpDecls = new SymbolHash(1);
      fGlobalElemDecls = new SymbolHash(6);
      fGlobalGroupDecls = new SymbolHash(1);
      fGlobalNotationDecls = new SymbolHash(1);
      fGlobalIDConstraintDecls = new SymbolHash(1);

      // no extended global decls
      fGlobalAttrDeclsExt = new SymbolHash(1);
      fGlobalAttrGrpDeclsExt = new SymbolHash(1);
      fGlobalElemDeclsExt = new SymbolHash(6);
      fGlobalGroupDeclsExt = new SymbolHash(1);
      fGlobalNotationDeclsExt = new SymbolHash(1);
      fGlobalIDConstraintDeclsExt = new SymbolHash(1);
      fGlobalTypeDeclsExt = new SymbolHash(1);

      // all global element declarations
      fAllGlobalElemDecls = new SymbolHash(6);

      // get all built-in types
      fGlobalTypeDecls = SG_SchemaNS.fGlobalTypeDecls;

      // create element declarations for <annotation>, <documentation> and <appinfo>
      XSElementDecl annotationDecl = createAnnotationElementDecl(SchemaSymbols.ELT_ANNOTATION);
      XSElementDecl documentationDecl = createAnnotationElementDecl(
          SchemaSymbols.ELT_DOCUMENTATION);
      XSElementDecl appinfoDecl = createAnnotationElementDecl(SchemaSymbols.ELT_APPINFO);

      // add global element declarations
      fGlobalElemDecls.put(annotationDecl.fName, annotationDecl);
      fGlobalElemDecls.put(documentationDecl.fName, documentationDecl);
      fGlobalElemDecls.put(appinfoDecl.fName, appinfoDecl);

      fGlobalElemDeclsExt.put("," + annotationDecl.fName, annotationDecl);
      fGlobalElemDeclsExt.put("," + documentationDecl.fName, documentationDecl);
      fGlobalElemDeclsExt.put("," + appinfoDecl.fName, appinfoDecl);

      fAllGlobalElemDecls.put(annotationDecl, annotationDecl);
      fAllGlobalElemDecls.put(documentationDecl, documentationDecl);
      fAllGlobalElemDecls.put(appinfoDecl, appinfoDecl);

      // create complex type declarations for <annotation>, <documentation> and <appinfo>
      XSComplexTypeDecl annotationType = new XSComplexTypeDecl();
      XSComplexTypeDecl documentationType = new XSComplexTypeDecl();
      XSComplexTypeDecl appinfoType = new XSComplexTypeDecl();

      // set the types on their element declarations
      annotationDecl.fType = annotationType;
      documentationDecl.fType = documentationType;
      appinfoDecl.fType = appinfoType;

      // create attribute groups for <annotation>, <documentation> and <appinfo>
      XSAttributeGroupDecl annotationAttrs = new XSAttributeGroupDecl();
      XSAttributeGroupDecl documentationAttrs = new XSAttributeGroupDecl();
      XSAttributeGroupDecl appinfoAttrs = new XSAttributeGroupDecl();

      // fill in attribute groups
      {
        // create and fill attribute uses for <annotation>, <documentation> and <appinfo>
        XSAttributeUseImpl annotationIDAttr = new XSAttributeUseImpl();
        annotationIDAttr.fAttrDecl = new XSAttributeDecl();
        annotationIDAttr.fAttrDecl.setValues(SchemaSymbols.ATT_ID, null,
            (XSSimpleType) fGlobalTypeDecls.get(SchemaSymbols.ATTVAL_ID),
            XSConstants.VC_NONE, XSConstants.SCOPE_LOCAL, null, annotationType, null);
        annotationIDAttr.fUse = SchemaSymbols.USE_OPTIONAL;
        annotationIDAttr.fConstraintType = XSConstants.VC_NONE;

        XSAttributeUseImpl documentationSourceAttr = new XSAttributeUseImpl();
        documentationSourceAttr.fAttrDecl = new XSAttributeDecl();
        documentationSourceAttr.fAttrDecl.setValues(SchemaSymbols.ATT_SOURCE, null,
            (XSSimpleType) fGlobalTypeDecls.get(SchemaSymbols.ATTVAL_ANYURI),
            XSConstants.VC_NONE, XSConstants.SCOPE_LOCAL, null, documentationType, null);
        documentationSourceAttr.fUse = SchemaSymbols.USE_OPTIONAL;
        documentationSourceAttr.fConstraintType = XSConstants.VC_NONE;

        XSAttributeUseImpl documentationLangAttr = new XSAttributeUseImpl();
        documentationLangAttr.fAttrDecl = new XSAttributeDecl();
        documentationLangAttr.fAttrDecl.setValues("lang".intern(), NamespaceContext.XML_URI,
            (XSSimpleType) fGlobalTypeDecls.get(SchemaSymbols.ATTVAL_LANGUAGE),
            XSConstants.VC_NONE, XSConstants.SCOPE_LOCAL, null, documentationType, null);
        documentationLangAttr.fUse = SchemaSymbols.USE_OPTIONAL;
        documentationLangAttr.fConstraintType = XSConstants.VC_NONE;

        XSAttributeUseImpl appinfoSourceAttr = new XSAttributeUseImpl();
        appinfoSourceAttr.fAttrDecl = new XSAttributeDecl();
        appinfoSourceAttr.fAttrDecl.setValues(SchemaSymbols.ATT_SOURCE, null,
            (XSSimpleType) fGlobalTypeDecls.get(SchemaSymbols.ATTVAL_ANYURI),
            XSConstants.VC_NONE, XSConstants.SCOPE_LOCAL, null, appinfoType, null);
        appinfoSourceAttr.fUse = SchemaSymbols.USE_OPTIONAL;
        appinfoSourceAttr.fConstraintType = XSConstants.VC_NONE;

        // create lax attribute wildcard for <annotation>, <documentation> and <appinfo>
        XSWildcardDecl otherAttrs = new XSWildcardDecl();
        otherAttrs.fNamespaceList = new String[]{fTargetNamespace, null};
        otherAttrs.fType = XSWildcard.NSCONSTRAINT_NOT;
        otherAttrs.fProcessContents = XSWildcard.PC_LAX;

        // add attribute uses and wildcards to attribute groups for <annotation>, <documentation> and <appinfo>
        annotationAttrs.addAttributeUse(annotationIDAttr);
        annotationAttrs.fAttributeWC = otherAttrs;

        documentationAttrs.addAttributeUse(documentationSourceAttr);
        documentationAttrs.addAttributeUse(documentationLangAttr);
        documentationAttrs.fAttributeWC = otherAttrs;

        appinfoAttrs.addAttributeUse(appinfoSourceAttr);
        appinfoAttrs.fAttributeWC = otherAttrs;
      }

      // create particles for <annotation>
      XSParticleDecl annotationParticle = createUnboundedModelGroupParticle();
      {
        XSModelGroupImpl annotationChoice = new XSModelGroupImpl();
        annotationChoice.fCompositor = XSModelGroupImpl.MODELGROUP_CHOICE;
        annotationChoice.fParticleCount = 2;
        annotationChoice.fParticles = new XSParticleDecl[2];
        annotationChoice.fParticles[0] = createChoiceElementParticle(appinfoDecl);
        annotationChoice.fParticles[1] = createChoiceElementParticle(documentationDecl);
        annotationParticle.fValue = annotationChoice;
      }

      // create wildcard particle for <documentation> and <appinfo>
      XSParticleDecl anyWCSequenceParticle = createUnboundedAnyWildcardSequenceParticle();

      // fill complex types
      annotationType.setValues("#AnonType_" + SchemaSymbols.ELT_ANNOTATION, fTargetNamespace,
          SchemaGrammar.fAnyType,
          XSConstants.DERIVATION_RESTRICTION, XSConstants.DERIVATION_NONE,
          (short) (XSConstants.DERIVATION_EXTENSION | XSConstants.DERIVATION_RESTRICTION),
          XSComplexTypeDecl.CONTENTTYPE_ELEMENT, false, annotationAttrs, null, annotationParticle,
          new XSObjectListImpl(null, 0));
      annotationType.setName("#AnonType_" + SchemaSymbols.ELT_ANNOTATION);
      annotationType.setIsAnonymous();

      documentationType.setValues("#AnonType_" + SchemaSymbols.ELT_DOCUMENTATION, fTargetNamespace,
          SchemaGrammar.fAnyType,
          XSConstants.DERIVATION_RESTRICTION, XSConstants.DERIVATION_NONE,
          (short) (XSConstants.DERIVATION_EXTENSION | XSConstants.DERIVATION_RESTRICTION),
          XSComplexTypeDecl.CONTENTTYPE_MIXED, false, documentationAttrs, null,
          anyWCSequenceParticle, new XSObjectListImpl(null, 0));
      documentationType.setName("#AnonType_" + SchemaSymbols.ELT_DOCUMENTATION);
      documentationType.setIsAnonymous();

      appinfoType.setValues("#AnonType_" + SchemaSymbols.ELT_APPINFO, fTargetNamespace,
          SchemaGrammar.fAnyType,
          XSConstants.DERIVATION_RESTRICTION, XSConstants.DERIVATION_NONE,
          (short) (XSConstants.DERIVATION_EXTENSION | XSConstants.DERIVATION_RESTRICTION),
          XSComplexTypeDecl.CONTENTTYPE_MIXED, false, appinfoAttrs, null, anyWCSequenceParticle,
          new XSObjectListImpl(null, 0));
      appinfoType.setName("#AnonType_" + SchemaSymbols.ELT_APPINFO);
      appinfoType.setIsAnonymous();

    } // <init>(int)

    // return the XMLGrammarDescription corresponding to this
    // object
    public XMLGrammarDescription getGrammarDescription() {
      return fGrammarDescription.makeClone();
    } // getGrammarDescription():  XMLGrammarDescription

    // override these methods solely so that these
    // objects cannot be modified once they're created.
    public void setImportedGrammars(Vector importedGrammars) {
      // ignore
    }

    public void addGlobalAttributeDecl(XSAttributeDecl decl) {
      // ignore
    }

    public void addGlobalAttributeDecl(XSAttributeGroupDecl decl, String location) {
      // ignore
    }

    public void addGlobalAttributeGroupDecl(XSAttributeGroupDecl decl) {
      // ignore
    }

    public void addGlobalAttributeGroupDecl(XSAttributeGroupDecl decl, String location) {
      // ignore
    }

    public void addGlobalElementDecl(XSElementDecl decl) {
      // ignore
    }

    public void addGlobalElementDecl(XSElementDecl decl, String location) {
      // ignore
    }

    public void addGlobalElementDeclAll(XSElementDecl decl) {
      // ignore
    }

    public void addGlobalGroupDecl(XSGroupDecl decl) {
      // ignore
    }

    public void addGlobalGroupDecl(XSGroupDecl decl, String location) {
      // ignore
    }

    public void addGlobalNotationDecl(XSNotationDecl decl) {
      // ignore
    }

    public void addGlobalNotationDecl(XSNotationDecl decl, String location) {
      // ignore
    }

    public void addGlobalTypeDecl(XSTypeDefinition decl) {
      // ignore
    }

    public void addGlobalTypeDecl(XSTypeDefinition decl, String location) {
      // ignore
    }

    public void addGlobalComplexTypeDecl(XSComplexTypeDecl decl) {
      // ignore
    }

    public void addGlobalComplexTypeDecl(XSComplexTypeDecl decl, String location) {
      // ignore
    }

    public void addGlobalSimpleTypeDecl(XSSimpleType decl) {
      // ignore
    }

    public void addGlobalSimpleTypeDecl(XSSimpleType decl, String location) {
      // ignore
    }

    public void addComplexTypeDecl(XSComplexTypeDecl decl, SimpleLocator locator) {
      // ignore
    }

    public void addRedefinedGroupDecl(XSGroupDecl derived, XSGroupDecl base,
        SimpleLocator locator) {
      // ignore
    }

    public synchronized void addDocument(Object document, String location) {
      // ignore
    }

    // annotation support
    synchronized DOMParser getDOMParser() {
      return null;
    }

    synchronized SAXParser getSAXParser() {
      return null;
    }

    //
    // private helper methods
    //

    private XSElementDecl createAnnotationElementDecl(String localName) {
      XSElementDecl eDecl = new XSElementDecl();
      eDecl.fName = localName;
      eDecl.fTargetNamespace = fTargetNamespace;
      eDecl.setIsGlobal();
      eDecl.fBlock = (XSConstants.DERIVATION_EXTENSION |
          XSConstants.DERIVATION_RESTRICTION | XSConstants.DERIVATION_SUBSTITUTION);
      eDecl.setConstraintType(XSConstants.VC_NONE);
      return eDecl;
    }

    private XSParticleDecl createUnboundedModelGroupParticle() {
      XSParticleDecl particle = new XSParticleDecl();
      particle.fMinOccurs = 0;
      particle.fMaxOccurs = SchemaSymbols.OCCURRENCE_UNBOUNDED;
      particle.fType = XSParticleDecl.PARTICLE_MODELGROUP;
      return particle;
    }

    private XSParticleDecl createChoiceElementParticle(XSElementDecl ref) {
      XSParticleDecl particle = new XSParticleDecl();
      particle.fMinOccurs = 1;
      particle.fMaxOccurs = 1;
      particle.fType = XSParticleDecl.PARTICLE_ELEMENT;
      particle.fValue = ref;
      return particle;
    }

    private XSParticleDecl createUnboundedAnyWildcardSequenceParticle() {
      XSParticleDecl particle = createUnboundedModelGroupParticle();
      XSModelGroupImpl sequence = new XSModelGroupImpl();
      sequence.fCompositor = XSModelGroupImpl.MODELGROUP_SEQUENCE;
      sequence.fParticleCount = 1;
      sequence.fParticles = new XSParticleDecl[1];
      sequence.fParticles[0] = createAnyLaxWildcardParticle();
      particle.fValue = sequence;
      return particle;
    }

    private XSParticleDecl createAnyLaxWildcardParticle() {
      XSParticleDecl particle = new XSParticleDecl();
      particle.fMinOccurs = 1;
      particle.fMaxOccurs = 1;
      particle.fType = XSParticleDecl.PARTICLE_WILDCARD;

      XSWildcardDecl anyWC = new XSWildcardDecl();
      anyWC.fNamespaceList = null;
      anyWC.fType = XSWildcard.NSCONSTRAINT_ANY;
      anyWC.fProcessContents = XSWildcard.PC_LAX;

      particle.fValue = anyWC;
      return particle;
    }
  }

  // Grammar methods

  // return the XMLGrammarDescription corresponding to this
  // object
  public XMLGrammarDescription getGrammarDescription() {
    return fGrammarDescription;
  } // getGrammarDescription():  XMLGrammarDescription

  // DTDGrammar methods
  public boolean isNamespaceAware() {
    return true;
  } // isNamespaceAware():boolean

  Vector fImported = null;

  public void setImportedGrammars(Vector importedGrammars) {
    fImported = importedGrammars;
  }

  public Vector getImportedGrammars() {
    return fImported;
  }

  /**
   * Returns this grammar's target namespace.
   */
  public final String getTargetNamespace() {
    return fTargetNamespace;
  } // getTargetNamespace():String

  /**
   * register one global attribute
   */
  public void addGlobalAttributeDecl(XSAttributeDecl decl) {
    fGlobalAttrDecls.put(decl.fName, decl);
    decl.setNamespaceItem(this);
  }

  public void addGlobalAttributeDecl(XSAttributeDecl decl, String location) {
    fGlobalAttrDeclsExt.put(((location != null) ? location : "") + "," + decl.fName, decl);
    if (decl.getNamespaceItem() == null) {
      decl.setNamespaceItem(this);
    }
  }

  /**
   * register one global attribute group
   */
  public void addGlobalAttributeGroupDecl(XSAttributeGroupDecl decl) {
    fGlobalAttrGrpDecls.put(decl.fName, decl);
    decl.setNamespaceItem(this);
  }

  public void addGlobalAttributeGroupDecl(XSAttributeGroupDecl decl, String location) {
    fGlobalAttrGrpDeclsExt.put(((location != null) ? location : "") + "," + decl.fName, decl);
    if (decl.getNamespaceItem() == null) {
      decl.setNamespaceItem(this);
    }
  }

  /**
   * register one global element
   */
  public void addGlobalElementDeclAll(XSElementDecl decl) {
    if (fAllGlobalElemDecls.get(decl) == null) {
      fAllGlobalElemDecls.put(decl, decl);
      // if there is a substitution group affiliation, store in an array,
      // for further constraint checking: UPA, PD, EDC
      if (decl.fSubGroup != null) {
        if (fSubGroupCount == fSubGroups.length) {
          fSubGroups = resize(fSubGroups, fSubGroupCount + INC_SIZE);
        }
        fSubGroups[fSubGroupCount++] = decl;
      }
    }
  }

  public void addGlobalElementDecl(XSElementDecl decl) {
    fGlobalElemDecls.put(decl.fName, decl);
    decl.setNamespaceItem(this);
  }

  public void addGlobalElementDecl(XSElementDecl decl, String location) {
    fGlobalElemDeclsExt.put(((location != null) ? location : "") + "," + decl.fName, decl);
    if (decl.getNamespaceItem() == null) {
      decl.setNamespaceItem(this);
    }
  }

  /**
   * register one global group
   */
  public void addGlobalGroupDecl(XSGroupDecl decl) {
    fGlobalGroupDecls.put(decl.fName, decl);
    decl.setNamespaceItem(this);
  }

  public void addGlobalGroupDecl(XSGroupDecl decl, String location) {
    fGlobalGroupDeclsExt.put(((location != null) ? location : "") + "," + decl.fName, decl);
    if (decl.getNamespaceItem() == null) {
      decl.setNamespaceItem(this);
    }
  }

  /**
   * register one global notation
   */
  public void addGlobalNotationDecl(XSNotationDecl decl) {
    fGlobalNotationDecls.put(decl.fName, decl);
    decl.setNamespaceItem(this);
  }

  public void addGlobalNotationDecl(XSNotationDecl decl, String location) {
    fGlobalNotationDeclsExt.put(((location != null) ? location : "") + "," + decl.fName, decl);
    if (decl.getNamespaceItem() == null) {
      decl.setNamespaceItem(this);
    }
  }

  /**
   * register one global type
   */
  public void addGlobalTypeDecl(XSTypeDefinition decl) {
    fGlobalTypeDecls.put(decl.getName(), decl);
    if (decl instanceof XSComplexTypeDecl) {
      ((XSComplexTypeDecl) decl).setNamespaceItem(this);
    } else if (decl instanceof XSSimpleTypeDecl) {
      ((XSSimpleTypeDecl) decl).setNamespaceItem(this);
    }
  }

  public void addGlobalTypeDecl(XSTypeDefinition decl, String location) {
    fGlobalTypeDeclsExt.put(((location != null) ? location : "") + "," + decl.getName(), decl);
    if (decl.getNamespaceItem() == null) {
      if (decl instanceof XSComplexTypeDecl) {
        ((XSComplexTypeDecl) decl).setNamespaceItem(this);
      } else if (decl instanceof XSSimpleTypeDecl) {
        ((XSSimpleTypeDecl) decl).setNamespaceItem(this);
      }
    }
  }

  /**
   * register one global complex type
   */
  public void addGlobalComplexTypeDecl(XSComplexTypeDecl decl) {
    fGlobalTypeDecls.put(decl.getName(), decl);
    decl.setNamespaceItem(this);
  }

  public void addGlobalComplexTypeDecl(XSComplexTypeDecl decl, String location) {
    fGlobalTypeDeclsExt.put(((location != null) ? location : "") + "," + decl.getName(), decl);
    if (decl.getNamespaceItem() == null) {
      decl.setNamespaceItem(this);
    }
  }

  /**
   * register one global simple type
   */
  public void addGlobalSimpleTypeDecl(XSSimpleType decl) {
    fGlobalTypeDecls.put(decl.getName(), decl);
    if (decl instanceof XSSimpleTypeDecl) {
      ((XSSimpleTypeDecl) decl).setNamespaceItem(this);
    }
  }

  public void addGlobalSimpleTypeDecl(XSSimpleType decl, String location) {
    fGlobalTypeDeclsExt.put(((location != null) ? location : "") + "," + decl.getName(), decl);
    if (decl.getNamespaceItem() == null && decl instanceof XSSimpleTypeDecl) {
      ((XSSimpleTypeDecl) decl).setNamespaceItem(this);
    }
  }

  /**
   * register one identity constraint
   */
  public final void addIDConstraintDecl(XSElementDecl elmDecl, IdentityConstraint decl) {
    elmDecl.addIDConstraint(decl);
    fGlobalIDConstraintDecls.put(decl.getIdentityConstraintName(), decl);
  }

  public final void addIDConstraintDecl(XSElementDecl elmDecl, IdentityConstraint decl,
      String location) {
    fGlobalIDConstraintDeclsExt
        .put(((location != null) ? location : "") + "," + decl.getIdentityConstraintName(), decl);
  }

  /**
   * get one global attribute
   */
  public final XSAttributeDecl getGlobalAttributeDecl(String declName) {
    return (XSAttributeDecl) fGlobalAttrDecls.get(declName);
  }

  public final XSAttributeDecl getGlobalAttributeDecl(String declName, String location) {
    return (XSAttributeDecl) fGlobalAttrDeclsExt
        .get(((location != null) ? location : "") + "," + declName);
  }

  /**
   * get one global attribute group
   */
  public final XSAttributeGroupDecl getGlobalAttributeGroupDecl(String declName) {
    return (XSAttributeGroupDecl) fGlobalAttrGrpDecls.get(declName);
  }

  public final XSAttributeGroupDecl getGlobalAttributeGroupDecl(String declName, String location) {
    return (XSAttributeGroupDecl) fGlobalAttrGrpDeclsExt
        .get(((location != null) ? location : "") + "," + declName);
  }

  /**
   * get one global element
   */
  public final XSElementDecl getGlobalElementDecl(String declName) {
    return (XSElementDecl) fGlobalElemDecls.get(declName);
  }

  public final XSElementDecl getGlobalElementDecl(String declName, String location) {
    return (XSElementDecl) fGlobalElemDeclsExt
        .get(((location != null) ? location : "") + "," + declName);
  }

  /**
   * get one global group
   */
  public final XSGroupDecl getGlobalGroupDecl(String declName) {
    return (XSGroupDecl) fGlobalGroupDecls.get(declName);
  }

  public final XSGroupDecl getGlobalGroupDecl(String declName, String location) {
    return (XSGroupDecl) fGlobalGroupDeclsExt
        .get(((location != null) ? location : "") + "," + declName);
  }

  /**
   * get one global notation
   */
  public final XSNotationDecl getGlobalNotationDecl(String declName) {
    return (XSNotationDecl) fGlobalNotationDecls.get(declName);
  }

  public final XSNotationDecl getGlobalNotationDecl(String declName, String location) {
    return (XSNotationDecl) fGlobalNotationDeclsExt
        .get(((location != null) ? location : "") + "," + declName);
  }

  /**
   * get one global type
   */
  public final XSTypeDefinition getGlobalTypeDecl(String declName) {
    return (XSTypeDefinition) fGlobalTypeDecls.get(declName);
  }

  public final XSTypeDefinition getGlobalTypeDecl(String declName, String location) {
    return (XSTypeDefinition) fGlobalTypeDeclsExt
        .get(((location != null) ? location : "") + "," + declName);
  }

  /**
   * get one identity constraint
   */
  public final IdentityConstraint getIDConstraintDecl(String declName) {
    return (IdentityConstraint) fGlobalIDConstraintDecls.get(declName);
  }

  public final IdentityConstraint getIDConstraintDecl(String declName, String location) {
    return (IdentityConstraint) fGlobalIDConstraintDeclsExt
        .get(((location != null) ? location : "") + "," + declName);
  }

  /**
   * get one identity constraint
   */
  public final boolean hasIDConstraints() {
    return fGlobalIDConstraintDecls.getLength() > 0;
  }

  // array to store complex type decls
  private static final int INITIAL_SIZE = 16;
  private static final int INC_SIZE = 16;

  private int fCTCount = 0;
  private XSComplexTypeDecl[] fComplexTypeDecls = new XSComplexTypeDecl[INITIAL_SIZE];
  private SimpleLocator[] fCTLocators = new SimpleLocator[INITIAL_SIZE];

  // an array to store groups being redefined by restriction
  // even-numbered elements are the derived groups, odd-numbered ones their bases
  private static final int REDEFINED_GROUP_INIT_SIZE = 2;
  private int fRGCount = 0;
  private XSGroupDecl[] fRedefinedGroupDecls = new XSGroupDecl[REDEFINED_GROUP_INIT_SIZE];
  private SimpleLocator[] fRGLocators = new SimpleLocator[REDEFINED_GROUP_INIT_SIZE / 2];

  // a flag to indicate whether we have checked the 3 constraints on this
  // grammar.
  boolean fFullChecked = false;

  /**
   * add one complex type decl: for later constraint checking
   */
  public void addComplexTypeDecl(XSComplexTypeDecl decl, SimpleLocator locator) {
    if (fCTCount == fComplexTypeDecls.length) {
      fComplexTypeDecls = resize(fComplexTypeDecls, fCTCount + INC_SIZE);
      fCTLocators = resize(fCTLocators, fCTCount + INC_SIZE);
    }
    fCTLocators[fCTCount] = locator;
    fComplexTypeDecls[fCTCount++] = decl;
  }

  /**
   * add a group redefined by restriction: for later constraint checking
   */
  public void addRedefinedGroupDecl(XSGroupDecl derived, XSGroupDecl base, SimpleLocator locator) {
    if (fRGCount == fRedefinedGroupDecls.length) {
      // double array size each time.
      fRedefinedGroupDecls = resize(fRedefinedGroupDecls, fRGCount << 1);
      fRGLocators = resize(fRGLocators, fRGCount);
    }
    fRGLocators[fRGCount / 2] = locator;
    fRedefinedGroupDecls[fRGCount++] = derived;
    fRedefinedGroupDecls[fRGCount++] = base;
  }

  /**
   * get all complex type decls: for later constraint checking
   */
  final XSComplexTypeDecl[] getUncheckedComplexTypeDecls() {
    if (fCTCount < fComplexTypeDecls.length) {
      fComplexTypeDecls = resize(fComplexTypeDecls, fCTCount);
      fCTLocators = resize(fCTLocators, fCTCount);
    }
    return fComplexTypeDecls;
  }

  /**
   * get the error locator of all complex type decls
   */
  final SimpleLocator[] getUncheckedCTLocators() {
    if (fCTCount < fCTLocators.length) {
      fComplexTypeDecls = resize(fComplexTypeDecls, fCTCount);
      fCTLocators = resize(fCTLocators, fCTCount);
    }
    return fCTLocators;
  }

  /**
   * get all redefined groups: for later constraint checking
   */
  final XSGroupDecl[] getRedefinedGroupDecls() {
    if (fRGCount < fRedefinedGroupDecls.length) {
      fRedefinedGroupDecls = resize(fRedefinedGroupDecls, fRGCount);
      fRGLocators = resize(fRGLocators, fRGCount / 2);
    }
    return fRedefinedGroupDecls;
  }

  /**
   * get the error locator of all redefined groups
   */
  final SimpleLocator[] getRGLocators() {
    if (fRGCount < fRedefinedGroupDecls.length) {
      fRedefinedGroupDecls = resize(fRedefinedGroupDecls, fRGCount);
      fRGLocators = resize(fRGLocators, fRGCount / 2);
    }
    return fRGLocators;
  }

  /**
   * after the first-round checking, some types don't need to be checked
   * against UPA again. here we trim the array to the proper size.
   */
  final void setUncheckedTypeNum(int newSize) {
    fCTCount = newSize;
    fComplexTypeDecls = resize(fComplexTypeDecls, fCTCount);
    fCTLocators = resize(fCTLocators, fCTCount);
  }

  // used to store all substitution group information declared in
  // this namespace
  private int fSubGroupCount = 0;
  private XSElementDecl[] fSubGroups = new XSElementDecl[INITIAL_SIZE];

  /**
   * get all substitution group information: for the 3 constraint checking
   */
  final XSElementDecl[] getSubstitutionGroups() {
    if (fSubGroupCount < fSubGroups.length) {
      fSubGroups = resize(fSubGroups, fSubGroupCount);
    }
    return fSubGroups;
  }

  // anyType and anySimpleType: because there are so many places where
  // we need direct access to these two types
  public final static XSComplexTypeDecl fAnyType = new XSAnyType();

  private static class XSAnyType extends XSComplexTypeDecl {

    public XSAnyType() {
      fName = SchemaSymbols.ATTVAL_ANYTYPE;
      super.fTargetNamespace = SchemaSymbols.URI_SCHEMAFORSCHEMA;
      fBaseType = this;
      fDerivedBy = XSConstants.DERIVATION_RESTRICTION;
      fContentType = XSComplexTypeDecl.CONTENTTYPE_MIXED;

      fParticle = null;
      fAttrGrp = null;
    }

    // overridden methods
    public void setValues(String name, String targetNamespace,
        XSTypeDefinition baseType, short derivedBy, short schemaFinal,
        short block, short contentType,
        boolean isAbstract, XSAttributeGroupDecl attrGrp,
        XSSimpleType simpleType, XSParticleDecl particle) {
      // don't allow this.
    }

    public void setName(String name) {
      // don't allow this.
    }

    public void setIsAbstractType() {
      // null implementation
    }

    public void setContainsTypeID() {
      // null implementation
    }

    public void setIsAnonymous() {
      // null implementation
    }

    public void reset() {
      // null implementation
    }

    public XSObjectList getAttributeUses() {
      return XSObjectListImpl.EMPTY_LIST;
    }

    public XSAttributeGroupDecl getAttrGrp() {
      XSWildcardDecl wildcard = new XSWildcardDecl();
      wildcard.fProcessContents = XSWildcardDecl.PC_LAX;
      XSAttributeGroupDecl attrGrp = new XSAttributeGroupDecl();
      attrGrp.fAttributeWC = wildcard;
      return attrGrp;
    }

    public XSWildcard getAttributeWildcard() {
      XSWildcardDecl wildcard = new XSWildcardDecl();
      wildcard.fProcessContents = XSWildcardDecl.PC_LAX;
      return wildcard;
    }

    public XSParticle getParticle() {
      // the wildcard used in anyType (content and attribute)
      // the spec will change strict to skip for anyType
      XSWildcardDecl wildcard = new XSWildcardDecl();
      wildcard.fProcessContents = XSWildcardDecl.PC_LAX;
      // the particle for the content wildcard
      XSParticleDecl particleW = new XSParticleDecl();
      particleW.fMinOccurs = 0;
      particleW.fMaxOccurs = SchemaSymbols.OCCURRENCE_UNBOUNDED;
      particleW.fType = XSParticleDecl.PARTICLE_WILDCARD;
      particleW.fValue = wildcard;
      // the model group of a sequence of the above particle
      XSModelGroupImpl group = new XSModelGroupImpl();
      group.fCompositor = XSModelGroupImpl.MODELGROUP_SEQUENCE;
      group.fParticleCount = 1;
      group.fParticles = new XSParticleDecl[1];
      group.fParticles[0] = particleW;
      // the content of anyType: particle of the above model group
      XSParticleDecl particleG = new XSParticleDecl();
      particleG.fType = XSParticleDecl.PARTICLE_MODELGROUP;
      particleG.fValue = group;

      return particleG;
    }

    public XSObjectList getAnnotations() {
      return XSObjectListImpl.EMPTY_LIST;
    }

    public XSNamespaceItem getNamespaceItem() {
      return SG_SchemaNS;
    }
  }

  private static class BuiltinAttrDecl extends XSAttributeDecl {

    public BuiltinAttrDecl(String name, String tns,
        XSSimpleType type, short scope) {
      fName = name;
      super.fTargetNamespace = tns;
      fType = type;
      fScope = scope;
    }

    public void setValues(String name, String targetNamespace,
        XSSimpleType simpleType, short constraintType, short scope,
        ValidatedInfo valInfo, XSComplexTypeDecl enclosingCT) {
      // ignore this call.
    }

    public void reset() {
      // also ignore this call.
    }

    public XSAnnotation getAnnotation() {
      return null;
    }

    public XSNamespaceItem getNamespaceItem() {
      return SG_XSI;
    }

  } // class BuiltinAttrDecl

  // the grammars to hold components of the schema namespace
  public final static BuiltinSchemaGrammar SG_SchemaNS = new BuiltinSchemaGrammar(GRAMMAR_XS,
      Constants.SCHEMA_VERSION_1_0);
  private final static BuiltinSchemaGrammar SG_SchemaNSExtended = new BuiltinSchemaGrammar(
      GRAMMAR_XS, Constants.SCHEMA_VERSION_1_0_EXTENDED);

  public final static XSSimpleType fAnySimpleType = (XSSimpleType) SG_SchemaNS
      .getGlobalTypeDecl(SchemaSymbols.ATTVAL_ANYSIMPLETYPE);

  // the grammars to hold components of the schema-instance namespace
  public final static BuiltinSchemaGrammar SG_XSI = new BuiltinSchemaGrammar(GRAMMAR_XSI,
      Constants.SCHEMA_VERSION_1_0);

  public static SchemaGrammar getS4SGrammar(short schemaVersion) {
    if (schemaVersion == Constants.SCHEMA_VERSION_1_0) {
      return SG_SchemaNS;
    } else {
      return SG_SchemaNSExtended;
    }
  }

  static final XSComplexTypeDecl[] resize(XSComplexTypeDecl[] oldArray, int newSize) {
    XSComplexTypeDecl[] newArray = new XSComplexTypeDecl[newSize];
    System.arraycopy(oldArray, 0, newArray, 0, Math.min(oldArray.length, newSize));
    return newArray;
  }

  static final XSGroupDecl[] resize(XSGroupDecl[] oldArray, int newSize) {
    XSGroupDecl[] newArray = new XSGroupDecl[newSize];
    System.arraycopy(oldArray, 0, newArray, 0, Math.min(oldArray.length, newSize));
    return newArray;
  }

  static final XSElementDecl[] resize(XSElementDecl[] oldArray, int newSize) {
    XSElementDecl[] newArray = new XSElementDecl[newSize];
    System.arraycopy(oldArray, 0, newArray, 0, Math.min(oldArray.length, newSize));
    return newArray;
  }

  static final SimpleLocator[] resize(SimpleLocator[] oldArray, int newSize) {
    SimpleLocator[] newArray = new SimpleLocator[newSize];
    System.arraycopy(oldArray, 0, newArray, 0, Math.min(oldArray.length, newSize));
    return newArray;
  }

  // XSNamespaceItem methods

  // the max index / the max value of XSObject type
  private static final short MAX_COMP_IDX = XSTypeDefinition.SIMPLE_TYPE;
  private static final boolean[] GLOBAL_COMP = {false,    // null
      true,     // attribute
      true,     // element
      true,     // type
      false,    // attribute use
      true,     // attribute group
      true,     // group
      false,    // model group
      false,    // particle
      false,    // wildcard
      false,    // idc
      true,     // notation
      false,    // annotation
      false,    // facet
      false,    // multi value facet
      true,     // complex type
      true      // simple type
  };

  // store a certain kind of components from all namespaces
  private XSNamedMap[] fComponents = null;
  private ObjectList[] fComponentsExt = null;

  // store the documents and their locations contributing to this namespace
  // REVISIT: use StringList and XSObjectList for there fields.
  private Vector fDocuments = null;
  private Vector fLocations = null;

  public synchronized void addDocument(Object document, String location) {
    if (fDocuments == null) {
      fDocuments = new Vector();
      fLocations = new Vector();
    }
    fDocuments.addElement(document);
    fLocations.addElement(location);
  }

  public synchronized void removeDocument(int index) {
    if (fDocuments != null &&
        index >= 0 &&
        index < fDocuments.size()) {
      fDocuments.removeElementAt(index);
      fLocations.removeElementAt(index);
    }
  }

  /**
   * [schema namespace]
   *
   * @return The target namespace of this item.
   * @see <a href="http://www.w3.org/TR/xmlschema-1/#nsi-schema_namespace">[schema namespace]</a>
   */
  public String getSchemaNamespace() {
    return fTargetNamespace;
  }

  // annotation support
  synchronized DOMParser getDOMParser() {
    if (fDOMParser != null) {
      DOMParser parser = (DOMParser) fDOMParser.get();
      if (parser != null) {
        return parser;
      }
    }
    // REVISIT:  when schema handles XML 1.1, will need to
    // revisit this (and the practice of not prepending an XML decl to the annotation string
    XML11Configuration config = new XML11Configuration(fSymbolTable);
    // note that this should never produce errors or require
    // entity resolution, so just a barebones configuration with
    // a couple of feature  set will do fine
    config.setFeature(Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE, true);
    config.setFeature(Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE, false);

    DOMParser parser = new DOMParser(config);
    try {
      parser.setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.DEFER_NODE_EXPANSION_FEATURE,
          false);
    } catch (SAXException exc) {
    }
    fDOMParser = new SoftReference(parser);
    return parser;
  }

  synchronized SAXParser getSAXParser() {
    if (fSAXParser != null) {
      SAXParser parser = (SAXParser) fSAXParser.get();
      if (parser != null) {
        return parser;
      }
    }
    // REVISIT:  when schema handles XML 1.1, will need to
    // revisit this (and the practice of not prepending an XML decl to the annotation string
    XML11Configuration config = new XML11Configuration(fSymbolTable);
    // note that this should never produce errors or require
    // entity resolution, so just a barebones configuration with
    // a couple of feature  set will do fine
    config.setFeature(Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE, true);
    config.setFeature(Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE, false);
    SAXParser parser = new SAXParser(config);
    fSAXParser = new SoftReference(parser);
    return parser;
  }

  /**
   * [schema components]: a list of top-level components, i.e. element
   * declarations, attribute declarations, etc.
   *
   * @param objectType The type of the declaration, i.e. <code>ELEMENT_DECLARATION</code>. Note that
   * <code>XSTypeDefinition.SIMPLE_TYPE</code> and <code>XSTypeDefinition.COMPLEX_TYPE</code> can
   * also be used as the <code>objectType</code> to retrieve only complex types or simple types,
   * instead of all types.
   * @return A list of top-level definition of the specified type in <code>objectType</code> or an
   * empty <code>XSNamedMap</code> if no such definitions exist.
   */
  public synchronized XSNamedMap getComponents(short objectType) {
    if (objectType <= 0 || objectType > MAX_COMP_IDX ||
        !GLOBAL_COMP[objectType]) {
      return XSNamedMapImpl.EMPTY_MAP;
    }

    if (fComponents == null) {
      fComponents = new XSNamedMap[MAX_COMP_IDX + 1];
    }

    // get the hashtable for this type of components
    if (fComponents[objectType] == null) {
      SymbolHash table = null;
      switch (objectType) {
        case XSConstants.TYPE_DEFINITION:
        case XSTypeDefinition.COMPLEX_TYPE:
        case XSTypeDefinition.SIMPLE_TYPE:
          table = fGlobalTypeDecls;
          break;
        case XSConstants.ATTRIBUTE_DECLARATION:
          table = fGlobalAttrDecls;
          break;
        case XSConstants.ELEMENT_DECLARATION:
          table = fGlobalElemDecls;
          break;
        case XSConstants.ATTRIBUTE_GROUP:
          table = fGlobalAttrGrpDecls;
          break;
        case XSConstants.MODEL_GROUP_DEFINITION:
          table = fGlobalGroupDecls;
          break;
        case XSConstants.NOTATION_DECLARATION:
          table = fGlobalNotationDecls;
          break;
      }

      // for complex/simple types, create a special implementation,
      // which take specific types out of the hash table
      if (objectType == XSTypeDefinition.COMPLEX_TYPE ||
          objectType == XSTypeDefinition.SIMPLE_TYPE) {
        fComponents[objectType] = new XSNamedMap4Types(fTargetNamespace, table, objectType);
      } else {
        fComponents[objectType] = new XSNamedMapImpl(fTargetNamespace, table);
      }
    }

    return fComponents[objectType];
  }

  public synchronized ObjectList getComponentsExt(short objectType) {
    if (objectType <= 0 || objectType > MAX_COMP_IDX ||
        !GLOBAL_COMP[objectType]) {
      return ObjectListImpl.EMPTY_LIST;
    }

    if (fComponentsExt == null) {
      fComponentsExt = new ObjectList[MAX_COMP_IDX + 1];
    }

    // get the hashtable for this type of components
    if (fComponentsExt[objectType] == null) {
      SymbolHash table = null;
      switch (objectType) {
        case XSConstants.TYPE_DEFINITION:
        case XSTypeDefinition.COMPLEX_TYPE:
        case XSTypeDefinition.SIMPLE_TYPE:
          table = fGlobalTypeDeclsExt;
          break;
        case XSConstants.ATTRIBUTE_DECLARATION:
          table = fGlobalAttrDeclsExt;
          break;
        case XSConstants.ELEMENT_DECLARATION:
          table = fGlobalElemDeclsExt;
          break;
        case XSConstants.ATTRIBUTE_GROUP:
          table = fGlobalAttrGrpDeclsExt;
          break;
        case XSConstants.MODEL_GROUP_DEFINITION:
          table = fGlobalGroupDeclsExt;
          break;
        case XSConstants.NOTATION_DECLARATION:
          table = fGlobalNotationDeclsExt;
          break;
      }

      Object[] entries = table.getEntries();
      fComponentsExt[objectType] = new ObjectListImpl(entries, entries.length);
    }

    return fComponentsExt[objectType];
  }

  public synchronized void resetComponents() {
    fComponents = null;
    fComponentsExt = null;
  }

  /**
   * Convenience method. Returns a top-level simple or complex type
   * definition.
   *
   * @param name The name of the definition.
   * @return An <code>XSTypeDefinition</code> or null if such definition does not exist.
   */
  public XSTypeDefinition getTypeDefinition(String name) {
    return getGlobalTypeDecl(name);
  }

  /**
   * Convenience method. Returns a top-level attribute declaration.
   *
   * @param name The name of the declaration.
   * @return A top-level attribute declaration or null if such declaration does not exist.
   */
  public XSAttributeDeclaration getAttributeDeclaration(String name) {
    return getGlobalAttributeDecl(name);
  }

  /**
   * Convenience method. Returns a top-level element declaration.
   *
   * @param name The name of the declaration.
   * @return A top-level element declaration or null if such declaration does not exist.
   */
  public XSElementDeclaration getElementDeclaration(String name) {
    return getGlobalElementDecl(name);
  }

  /**
   * Convenience method. Returns a top-level attribute group definition.
   *
   * @param name The name of the definition.
   * @return A top-level attribute group definition or null if such definition does not exist.
   */
  public XSAttributeGroupDefinition getAttributeGroup(String name) {
    return getGlobalAttributeGroupDecl(name);
  }

  /**
   * Convenience method. Returns a top-level model group definition.
   *
   * @param name The name of the definition.
   * @return A top-level model group definition definition or null if such definition does not
   * exist.
   */
  public XSModelGroupDefinition getModelGroupDefinition(String name) {
    return getGlobalGroupDecl(name);
  }

  /**
   * Convenience method. Returns a top-level notation declaration.
   *
   * @param name The name of the declaration.
   * @return A top-level notation declaration or null if such declaration does not exist.
   */
  public XSNotationDeclaration getNotationDeclaration(String name) {
    return getGlobalNotationDecl(name);
  }


  /**
   * [document location]
   *
   * @return a list of document information item
   * @see <a href="http://www.w3.org/TR/xmlschema-1/#sd-document_location">[document location]</a>
   */
  public StringList getDocumentLocations() {
    return new StringListImpl(fLocations);
  }

  /**
   * Return an <code>XSModel</code> that represents components in this schema
   * grammar.
   *
   * @return an <code>XSModel</code> representing this schema grammar
   */
  public XSModel toXSModel() {
    return new XSModelImpl(new SchemaGrammar[]{this});
  }

  public XSModel toXSModel(XSGrammar[] grammars) {
    if (grammars == null || grammars.length == 0) {
      return toXSModel();
    }

    int len = grammars.length;
    boolean hasSelf = false;
    for (int i = 0; i < len; i++) {
      if (grammars[i] == this) {
        hasSelf = true;
        break;
      }
    }

    SchemaGrammar[] gs = new SchemaGrammar[hasSelf ? len : len + 1];
    for (int i = 0; i < len; i++) {
      gs[i] = (SchemaGrammar) grammars[i];
    }
    if (!hasSelf) {
      gs[len] = this;
    }
    return new XSModelImpl(gs);
  }

  /**
   * @see org.apache.xerces.xs.XSNamespaceItem#getAnnotations()
   */
  public XSObjectList getAnnotations() {
    if (fNumAnnotations == 0) {
      return XSObjectListImpl.EMPTY_LIST;
    }
    return new XSObjectListImpl(fAnnotations, fNumAnnotations);
  }

  public void addAnnotation(XSAnnotationImpl annotation) {
    if (annotation == null) {
      return;
    }
    if (fAnnotations == null) {
      fAnnotations = new XSAnnotationImpl[2];
    } else if (fNumAnnotations == fAnnotations.length) {
      XSAnnotationImpl[] newArray = new XSAnnotationImpl[fNumAnnotations << 1];
      System.arraycopy(fAnnotations, 0, newArray, 0, fNumAnnotations);
      fAnnotations = newArray;
    }
    fAnnotations[fNumAnnotations++] = annotation;
  }

  public void setImmutable(boolean isImmutable) {
    fIsImmutable = isImmutable;
  }

  public boolean isImmutable() {
    return fIsImmutable;
  }

} // class SchemaGrammar
